package Gear;

import Connections.Tracker;
import Connections.PeerServer;


/**
 * Singleton factory which allows access to almost all critical objects.
 *
 * @author Davi Mendes
 */
public class Factory {

    /**
     * Factory instance.
     */
    private static Factory instance;

    /**
     * Executions setting.
     */
    private final Settings settings;

    /**
     * Local mutex (singleton) which ensures local race conditions.
     */
    private final LocalFileMutex lfMutex;

    /**
     * Tracker instance (singleton) if necessary.
     */
    private Tracker tracker;

    /**
     * Peer server instance (singleton) if necessary.
     */
    private PeerServer peerServer;


    /**
     * Factory constructor.
     * Initialize settings and localFileMutex.
     */
    private Factory() {
        this.settings = new Settings();
        this.lfMutex = new LocalFileMutex();
    }

    /**
     * Get factory instance.
     *
     * @return Factory instance.
     */
    public static Factory getInstance() {
        if (instance == null) instance = new Factory();

        return instance;
    }

    /**
     * Get settings.
     *
     * @return Settings.
     */
    public Settings getSettings() {
        return this.settings;
    }

    /**
     * Initialize factory instance of.
     */
    public static void initFactory() {
        instance = new Factory();
    }

    /**
     * Get tracker instance.
     *
     * @return Tracker instance.
     */
    public Tracker getTracker() {
        synchronized (this) {
            if (tracker == null) tracker = new Tracker("Tracker");
        }

        return tracker;
    }

    /**
     * Get peer server instance.
     *
     * @return Peer server.
     */
    public PeerServer getPeerServer() {
        synchronized (this) {
            if (peerServer == null) peerServer = new PeerServer("Peer");
        }

        return peerServer;
    }

    /**
     * Get local file mutex.
     *
     * @return Local file mutex.
     */
    public LocalFileMutex getLocalFileMutex() {
        return this.lfMutex;
    }
}
